package com.trg.flex
{
	import flash.events.EventDispatcher;
	
	import mx.collections.IList;
	import mx.events.CollectionEvent;

	/**
	 * <p>This class was created to help with dropdown combo boxes where there is an extra "None"
	 * option. It provides a view of any given list with a single object prepended to the beginning.
	 * When the underlying list changes, this view automatically updates.
	 * 
	 * <p>Here's an example usage. (NOTE:  <code>emptyOption = {id: 0, name: "[ None ]"}</code> ):
	 * <pre>
	 *  &lt;mx:ComboBox id="itemLocation" labelField="name"&gt;
	 *    &lt;mx:dataProvider&gt;
	 *      &lt;components:ListWithPrepend list="{locations}" prepend="{emptyOption}"/&gt;
	 *    &lt;/mx:dataProvider&gt;
	 *  &lt;/mx:ComboBox&gt;
	 * </pre>
	 */
	public class ListWithPrepend extends EventDispatcher implements IList
	{
		public function ListWithPrepend(list:IList=null, prepend:*=null) {
			this.list = list;
			this.prepend = prepend;
		}

		private var _prepend:*;
		
		public function set prepend(value:*):void {
			_prepend = value;
			if (_list != null) dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE));
		}
		
		/**
		 * The item to add to the beginning.
		 */
		public function get prepend():* {
			return _prepend;
		}
		
		private var _list:IList;
		
		public function set list(value:IList):void {
			if (_list == value) return;
			
			if (_list != null) _list.removeEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
			_list = value;
			if (_list != null) {
				try {
					if ( typeof _list['refresh'] == "function" &&
					(_list['filterFunction'] != null || _list['sort'] != null)) {
						_list['refresh']();
					}
				} catch (e:*) {}
				_list.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
			}
			dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE));
		}
		
		/**
		 * The underlying list.
		 */
		public function get list():IList {
			return _list;
		}
		
		private function collectionChangeHandler(event:CollectionEvent):void {
			dispatchEvent(event);
		}
		
		// ---------- IList Interface ----------
			
		public function get length():int {
			if (_list == null) return 0;
			return _list.length + (_prepend == null ? 0 : 1);
		}
		
		public function addItem(item:Object):void {
			throw new Error("Not Implemented");
		}
		public function addItemAt(item:Object, index:int):void {
			throw new Error("Not Implemented");
		}
		public function getItemAt(index:int, prefetch:int = 0):Object {
			if (_list == null) return null;
			
			if (index == 0) return _prepend;
			return _list.getItemAt(index - 1, prefetch);
		}
		public function getItemIndex(item:Object):int {
			if (_list == null) return -1;
			
			if (item == _prepend) return 0;
			return _list.getItemIndex(item);
		}
		public function itemUpdated(item:Object, property:Object = null, oldValue:Object = null, newValue:Object = null):void  {
			throw new Error("Not Implemented");
		}
		public function removeAll():void {
			throw new Error("Not Implemented");
		}
		public function removeItemAt(index:int):Object {
			throw new Error("Not Implemented");
		}
		public function setItemAt(item:Object, index:int):Object {
			throw new Error("Not Implemented");
		}
		public function toArray():Array {
			if (_list == null) return null;
			
			return [ _prepend ].concat(_list.toArray());
		}
	}
}